﻿using System;
using System.Diagnostics.Contracts;
using Moq;

namespace Postnuclear.Test.Helpers
  {
  /// <summary>
  /// Extension methods for test purposes.
  /// </summary>
  public static class ExtensionMethods
    {
    #region Public

    // Methods

    /// <summary>
    /// Sets the <see cref="IValueProvider{TValue}.Value"/> for specified <see cref="IValueProvider{TValue}"/> and raises the <see cref="INotifyValueChanged.ValueChanged"/> event.
    /// </summary>
    /// <typeparam name="TMock">The type of the mocked object.</typeparam>
    /// <typeparam name="TValue">The type of the value.</typeparam>
    /// <param name="mock">The mock value provider.</param>
    /// <param name="value">The new value.</param>
    public static void SetAndRaise<TMock, TValue>(this Mock<TMock> mock, TValue value)
      where TMock : class, IValueProvider<TValue>
      {
      Contract.Requires<ArgumentNullException>(mock != null);

      Contract.Ensures(object.Equals(mock.Object.Value, value));

      mock.SetupGet(m => m.Value).Returns(value);
      mock.RaiseValueChanged();
      }

    /// <summary>
    /// Raises the <see cref="INotifyValueChanged.ValueChanged"/> event.
    /// </summary>
    /// <typeparam name="TMock">The type of the mocked object.</typeparam>
    /// <param name="mock">The mock value provider.</param>
    public static void RaiseValueChanged<TMock>(this Mock<TMock> mock)
      where TMock : class, INotifyValueChanged
      {
      Contract.Requires<ArgumentNullException>(mock != null);

      mock.Raise(m => m.ValueChanged += null, EventArgs.Empty);
      }

    #endregion
    }
  }
